package com.bitcoin.scheduler.service;

import com.bitcoin.scheduler.domain.blockcc.KLineBlockCC;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MarketBinanceApiService {
    public final static String MARKET_NAME = "binance";

    @Autowired
    private ObjectMapper jsonMapper;

    private final static Map<String, Integer> symbols = Maps.newLinkedHashMap();

    static {
        symbols.put("BTC", 1);
        symbols.put("ETH", 2);
        symbols.put("XRP", 3);
        symbols.put("BNB", 22);
        symbols.put("EOS", 5);
        symbols.put("ETC", 17);
        symbols.put("NEO", 11);
        symbols.put("TRX", 9);
        symbols.put("XLM", 8);
        symbols.put("ADA", 6);
        symbols.put("LTC", 7);
        symbols.put("ONT", 31);
        symbols.put("IOTA", 10);
        symbols.put("QTUM", 18);
        symbols.put("AE", 27);
        symbols.put("BAT", 54);
        symbols.put("BCD", 39);
        symbols.put("BCX", 19);
        symbols.put("BOT", 374);
        symbols.put("BTG", 26);
        symbols.put("BTM", 32);
        symbols.put("BTO", 124);
        symbols.put("BTS", 34);
        symbols.put("CDT", 235);
        symbols.put("DCR", 49);
        symbols.put("DGD", 51);
        symbols.put("ELF", 55);
        symbols.put("FIL", 24);
        symbols.put("GNT", 60);
        symbols.put("GTC", 146);
        symbols.put("GXS", 90);
        symbols.put("HT", 138);
        symbols.put("IHT", 201);
        symbols.put("LINK", 103);
        symbols.put("LRC", 53);
        symbols.put("MANA", 104);
        symbols.put("MCO", 106);
        symbols.put("MKR", 44);
        symbols.put("NANO", 29);
        symbols.put("NAS", 66);
        symbols.put("PAY", 109);
        symbols.put("POWR", 100);
        symbols.put("RUFF", 141);
        symbols.put("SNT", 50);
        symbols.put("WAVES", 43);
        symbols.put("XVG", 25);
        symbols.put("ZEC", 28);
        symbols.put("ZIL", 41);
        symbols.put("ZRX", 46);
        symbols.put("ZSC", 372);
    }

    @Transactional
    public List<KLineBlockCC> getKlineResponse(String symbol, int days) throws IOException, InterruptedException {
        long startTime = System.currentTimeMillis();
        Thread.sleep(1000);
        String response;
        try {
            Date day = DateUtils.addDays(new Date(), -days);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(day);
            calendar.set(Calendar.HOUR_OF_DAY, 0);
            calendar.set(Calendar.MINUTE, 0);
            calendar.set(Calendar.SECOND, 0);
            calendar.set(Calendar.MILLISECOND, 0);
            log.info("币安交易 查询开始时间 {}", DateFormatUtils.format(calendar.getTime(), "yyyy/MM/dd HH:mm:ss"));
            long start = calendar.getTimeInMillis();
            calendar.setTime(DateUtils.addDays(calendar.getTime(), 3));
            calendar.set(Calendar.HOUR, 23);
            calendar.set(Calendar.MINUTE, 59);
            calendar.set(Calendar.SECOND, 59);
            calendar.set(Calendar.MILLISECOND, 999);
            log.info("币安交易 查询结束时间 {}", DateFormatUtils.format(calendar.getTime(), "yyyy/MM/dd HH:mm:ss"));
            long end = calendar.getTimeInMillis();
            response = Jsoup.connect("https://api.binance.com/api/v1/klines").ignoreContentType(true)
                .data("symbol", symbol + "USDT")
                .data("interval", "5m")
                .data("limit","5000")
                .data("startTime", String.valueOf(start))
                .data("endTime", String.valueOf(end))
                .proxy("172.16.247.39", 1080)
                .timeout(5 * 60 * 1000)
                .execute().body();
        } catch (Exception e) {
            Thread.sleep(3000);
            return getKlineResponse(symbol, days);
        }

        List dataList = jsonMapper.readValue(response, new TypeReference<List>() {
        });
        List<KLineBlockCC> lineList = Lists.newArrayList();

        log.info("数据读取完毕 {}条 币标识符{} 耗时 {}ms", dataList.size(), symbol, System.currentTimeMillis() - startTime);
        if (CollectionUtils.isEmpty(dataList)) {
            return lineList;
        }
        for (Object data : dataList) {
            List info = (List) data;
            KLineBlockCC line = new KLineBlockCC();
            line.setBccId(symbols.get(symbol));
            line.setCurrency("USDT");
            line.setPriceTime(new Date((long) info.get(0)));
            line.setSymbol(symbol);
            line.setMarket(MARKET_NAME);
            line.setOpenPrice(BigDecimal.valueOf(NumberUtils.toDouble(info.get(1).toString())));
            line.setHighPrice(BigDecimal.valueOf((NumberUtils.toDouble(info.get(2).toString()))));
            line.setLowPrice(BigDecimal.valueOf((NumberUtils.toDouble(info.get(3).toString()))));
            line.setClosePrice(BigDecimal.valueOf(NumberUtils.toDouble(info.get(4).toString())));
            line.setVolume(BigDecimal.valueOf(NumberUtils.toDouble(info.get(5).toString())));
            lineList.add(line);
        }
        return lineList;
    }
}
